001 /* 002 * Copyright 2004-2005 Stephen J. McConnell. 003 * Copyright 1999-2004 The Apache Software Foundation 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 014 * implied. 015 * 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 package net.dpml.i18n; 020 021 import java.lang.ref.WeakReference; 022 import java.util.HashMap; 023 import java.util.Locale; 024 025 /** 026 * Manager for resources. 027 * 028 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 029 * @version 1.0.0 030 */ 031 public final class ResourceManager 032 { 033 /** 034 * Permission needed to clear complete cache. 035 */ 036 private static final RuntimePermission CLEAR_CACHE_PERMISSION = 037 new RuntimePermission( "i18n.clearCompleteCache" ); 038 039 /** 040 * Resource lookup table. 041 */ 042 private static final HashMap RESOURCES = new HashMap(); 043 044 /** 045 * Retrieve resource with specified basename. 046 * 047 * @param baseName the basename 048 * @return the Resources 049 */ 050 public static final Resources getBaseResources( final String baseName ) 051 { 052 return getBaseResources( baseName, null ); 053 } 054 055 /** 056 * Retrieve resource with specified basename. 057 * 058 * @param baseName the basename 059 * @param classLoader the classLoader to load resources from 060 * @return the Resources 061 */ 062 public static final synchronized Resources getBaseResources( 063 final String baseName, final ClassLoader classLoader ) 064 { 065 Resources resources = getCachedResource( baseName ); 066 if( null == resources ) 067 { 068 resources = new Resources( baseName, classLoader ); 069 putCachedResource( baseName, resources ); 070 } 071 072 return resources; 073 } 074 075 /** 076 * Retrieve resource with specified basename. 077 * 078 * @param baseName the basename 079 * @param locale the locale 080 * @param classLoader the classLoader to load resources from 081 * @return the Resources 082 */ 083 public static final synchronized Resources getBaseResources( 084 final String baseName, final Locale locale, final ClassLoader classLoader ) 085 { 086 Resources resources = getCachedResource( baseName + "_" + locale.hashCode() ); 087 if( null == resources ) 088 { 089 resources = new Resources( baseName, locale, classLoader ); 090 putCachedResource( baseName + "_" + locale.hashCode(), resources ); 091 } 092 093 return resources; 094 } 095 096 /** 097 * Clear the cache of all resources currently loaded into the 098 * system. This method is useful if you need to dump the complete 099 * cache and because part of the application is reloading and 100 * thus the resources may need to be reloaded. 101 * 102 * <p>Note that the caller must have been granted the 103 * "i18n.clearCompleteCache" {@link RuntimePermission} or 104 * else a security exception will be thrown.</p> 105 * 106 * @throws SecurityException if the caller does not have 107 * permission to clear cache 108 */ 109 public static final synchronized void clearResourceCache() 110 throws SecurityException 111 { 112 final SecurityManager sm = System.getSecurityManager(); 113 if( null != sm ) 114 { 115 sm.checkPermission( CLEAR_CACHE_PERMISSION ); 116 } 117 118 RESOURCES.clear(); 119 } 120 121 /** 122 * Cache specified resource in weak reference. 123 * 124 * @param baseName the resource key 125 * @param resources the resources object 126 */ 127 private static final synchronized void putCachedResource( 128 final String baseName, final Resources resources ) 129 { 130 RESOURCES.put( baseName, new WeakReference( resources ) ); 131 } 132 133 /** 134 * Retrieve cached resource. 135 * 136 * @param baseName the resource key 137 * @return resources the resources object 138 */ 139 private static final synchronized Resources getCachedResource( final String baseName ) 140 { 141 final WeakReference weakReference = 142 (WeakReference) RESOURCES.get( baseName ); 143 if( null == weakReference ) 144 { 145 return null; 146 } 147 else 148 { 149 return (Resources) weakReference.get(); 150 } 151 } 152 153 /** 154 * Retrieve resource for specified name. 155 * The basename is determined by name postfixed with ".Resources". 156 * 157 * @param name the name to use when looking up resources 158 * @return the Resources 159 */ 160 public static final Resources getResources( final String name ) 161 { 162 return getBaseResources( name + ".Resources" ); 163 } 164 165 /** 166 * Retrieve resource for specified Classes package. 167 * The basename is determined by name of classes package 168 * postfixed with ".Resources". 169 * 170 * @param clazz the Class 171 * @return the Resources 172 */ 173 public static final Resources getPackageResources( final Class clazz ) 174 { 175 return getBaseResources( getPackageResourcesBaseName( clazz ), clazz.getClassLoader() ); 176 } 177 178 /** 179 * Retrieve resource for specified Classes package. 180 * The basename is determined by name of classes package 181 * postfixed with ".Resources". 182 * 183 * @param clazz the Class 184 * @param locale the locale 185 * @return the Resources 186 */ 187 public static final Resources getPackageResources( final Class clazz, Locale locale ) 188 { 189 return getBaseResources( getPackageResourcesBaseName( clazz ), locale, clazz.getClassLoader() ); 190 } 191 192 /** 193 * Retrieve resource for specified Class. 194 * The basename is determined by name of Class 195 * postfixed with "Resources". 196 * 197 * @param clazz the Class 198 * @return the Resources 199 */ 200 public static final Resources getClassResources( final Class clazz ) 201 { 202 return getBaseResources( getClassResourcesBaseName( clazz ), clazz.getClassLoader() ); 203 } 204 205 /** 206 * Retrieve resource for specified Class. 207 * The basename is determined by name of Class 208 * postfixed with "Resources". 209 * 210 * @param clazz the Class 211 * @param locale the requested Locale. 212 * @return the Resources 213 */ 214 public static final Resources getClassResources( final Class clazz, Locale locale ) 215 { 216 return getBaseResources( getClassResourcesBaseName( clazz ), locale, clazz.getClassLoader() ); 217 } 218 219 /** 220 * Retrieve resource basename for specified Classes package. 221 * The basename is determined by name of classes package 222 * postfixed with ".Resources". 223 * 224 * @param clazz the Class 225 * @return the resource basename 226 */ 227 public static final String getPackageResourcesBaseName( final Class clazz ) 228 { 229 final Package pkg = clazz.getPackage(); 230 231 String baseName; 232 if( null == pkg ) 233 { 234 final String name = clazz.getName(); 235 if( -1 == name.lastIndexOf( "." ) ) 236 { 237 baseName = "Resources"; 238 } 239 else 240 { 241 baseName = name.substring( 0, name.lastIndexOf( "." ) ) + ".Resources"; 242 } 243 } 244 else 245 { 246 baseName = pkg.getName() + ".Resources"; 247 } 248 249 return baseName; 250 } 251 252 /** 253 * Retrieve resource basename for specified Class. 254 * The basename is determined by name of Class 255 * postfixed with "Resources". 256 * 257 * @param clazz the Class 258 * @return the resource basename 259 */ 260 public static final String getClassResourcesBaseName( final Class clazz ) 261 { 262 return clazz.getName() + "Resources"; 263 } 264 265 /** 266 * Private Constructor to block instantiation. 267 */ 268 private ResourceManager() 269 { 270 } 271 }